﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using ArgusLight.Reflection;
using ArgusLight.Fractals2D;
using ArgusControls;
using ATreeViewItem = ArgusControls.TreeViewItem_OneClickExpand;

namespace Fractals
{
	public partial class SelectColoringWindow : ChildWindow
	{
		public Size MaxImageSize { get; private set; }

		public Coloring SelectedColoring { get; private set; }
		public ImageSource PreviewImage { get; private set; }

		private Type coloringType;
		private List<Fractal> fractals;
		private Dictionary<Type, List<Coloring>> colorings;

		public SelectColoringWindow()
		{
			this.SelectedColoring = null;
			this.MaxImageSize = new Size(50, 50);
			InitializeComponent();
		}

		public void Show(FractalParameter fParameter, Type BaseColor, Type FractalType)
		{
			this.InitializeColorUI(fParameter, BaseColor, FractalType);
			base.Show();
		}

		private void InitializeColorUI(FractalParameter fParameter, Type BaseColor, Type FractalType)
		{
			this.treeView.Items.Clear();
			this.fractals = new List<Fractal>();
			this.colorings = new Dictionary<Type, List<Coloring>>();
			TypeFilter filter = new TypeFilter();
			filter.DerivedFrom = BaseColor;
			filter.IncludeAbstract = false;
			Dictionary<string, ATreeViewItem> parents = new Dictionary<string, ATreeViewItem>();
			Type[] types = AssemblyReflector.GetTypes(filter);
			foreach (Type t in types)
			{
#if DEBUG
#else
				if (t.GetCustomAttributes(typeof(AlphaAttribute), true).Length > 0)
					continue;
#endif
				int i = t.Namespace.LastIndexOf('.');
				string text;
				if (i < 0)
					text = t.Namespace;
				else
					text = t.Namespace.Substring(i + 1);

				if (parents.ContainsKey(text) == false)
				{
					ATreeViewItem tvi = new ATreeViewItem();
					tvi.Foreground = this.Foreground;
					string localized = Localization.Colorings.ResourceManager.GetString(text);
					if (string.IsNullOrWhiteSpace(localized) == true)
						tvi.Header = text;
					else
						tvi.Header = localized;
					this.treeView.Items.Add(tvi);
					parents.Add(text, tvi);
				}

				ImageTreeViewItem itvi = new ImageTreeViewItem();
				itvi.Foreground = this.Foreground;
				string loc = Localization.Colorings.ResourceManager.GetString(t.Name);
				if (string.IsNullOrWhiteSpace(loc) == true)
					itvi.HeaderText = t.Name;
				else
					itvi.HeaderText = loc;
				itvi.Name = t.AssemblyQualifiedName;
				parents[text].Items.Add(itvi);

				Dictionary<Type, List<Coloring>>.KeyCollection.Enumerator e = this.colorings.Keys.GetEnumerator();
				bool already = false;
				Coloring c = (Coloring)Activator.CreateInstance(t);
				while (e.MoveNext() == true)
				{
					//Rethink whole method: ColoringConverter
					//Coloring c = e.Current.ConvertTo(t);
					//if (c == null)
					//	continue;

					if (ColoringConverter.ConversionExists(e.Current, t) == false)
						continue;

					already = true;
					this.colorings[e.Current].Add(c);
					break;
				}

				if (already == false)
				{
					this.colorings.Add(t, new List<Coloring>());
					Fractal fractal = (Fractal)Activator.CreateInstance(FractalType);
					fractal.CalculationFinished += fractal_CalculationFinished;
					FractalParameter para = fParameter.GetCopy();
					Size s = this.MaxImageSize.ChangeRatio((new Size(fParameter.PixelWidth, fParameter.PixelHeight)).GetRatio(), System.Windows.ExtensionMethods.ChangeRatioOptions.DecreaseAreaSize);
					para.PixelWidth = (int)s.Width;
					para.PixelHeight = (int)s.Height;
					fractal.SetColoring(c);
					fractal.StartCalculation(para);
					this.fractals.Add(fractal);
				}
			}
		}

		void fractal_CalculationFinished(object sender, CalculationFinishedArgs e)
		{
			Fractal Sender = (Fractal)sender;
			ImageTreeViewItem itvi = (ImageTreeViewItem)this.treeView.FindName(Sender.Coloring.GetType().AssemblyQualifiedName);
			if (itvi != null)
				itvi.HeaderImage = Sender.GetImage();

			List<Coloring> l = this.colorings[Sender.Coloring.GetType()];
			foreach (Coloring c in l)
			{
				itvi = (ImageTreeViewItem)this.treeView.FindName(c.GetType().AssemblyQualifiedName);
				if (itvi == null)
					continue;
				Sender.SetColoring(c);
				itvi.HeaderImage = Sender.GetImage();
			}
		}

		private void bOK_Click(object sender, RoutedEventArgs e)
		{
			this.SelectedColoring = (Coloring)Activator.CreateInstance(this.coloringType);
			this.DialogResult = true;
			//this.Close();
		}

		private void bCancel_Click(object sender, RoutedEventArgs e)
		{
			this.SelectedColoring = null;
			this.DialogResult = false;
			//this.Close();
		}

		protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
		{
			base.OnClosing(e);
			foreach (Fractal f in this.fractals)
			{
				f.RequestCalculationCancelation();
			}
		}

		private void treeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
		{
			if (e.NewValue is ImageTreeViewItem)
			{
				ImageTreeViewItem itvi = (ImageTreeViewItem)e.NewValue;
				this.PreviewImage = itvi.HeaderImage;
				this.coloringType = Type.GetType(itvi.Name);
				if (this.coloringType == null || this.coloringType.IsSubclassOf(typeof(Coloring)) == false)
				{
					this.coloringType = null;
					this.bOK.IsEnabled = false;
					return;
				}
				else
				{
					this.bOK.IsEnabled = true;
				}
			}
			else
			{
				this.coloringType = null;
				this.bOK.IsEnabled = false;
			}
		}
	}
}

